package com.ls.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ls.config.redis.RedisClient;
import com.ls.config.satoken.SaTokenUtilPy;
import com.ls.constant.SystemConstants;
import com.ls.controller.customer.model.*;
import com.ls.controller.customer.model.UpdateStatusModel;
import com.ls.entity.*;
import com.ls.enums.RoleEnum;
import com.ls.enums.SignEnum;
import com.ls.exception.ErrorEnums;
import com.ls.exception.SysException;
import com.ls.mapper.CustomerMapper;
import com.ls.service.*;
import com.ls.utils.*;
import com.ls.utils.pay.TimeUtils;
import com.ls.utils.sms.SendSmsModel;
import com.ls.utils.sms.SmsPyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import static com.ls.constant.SystemConstants.*;
import static com.ls.enums.OrderRecordEnum.getOrderRecordEnum;
import static com.ls.utils.VerifyCodeUtil.TYPE_NUM_ONLY;
import static com.ls.utils.rsa.RsaUtils.getRsaDecryStr;

/**
 * <p>
 * C端用户表 服务实现类
 * </p>
 *
 * @author pengyu
 * @since 2023-03-13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements ICustomerService {
    // 新增环境依赖注入
    private final Environment env;
    private final RedisClient redisClient;
    private final IPhoneIspService phoneIspService;
    private final ISmsRuleService ruleService;
    private final IBlackListService blackListService;
    private final IFeedbackRecordService feedbackRecordService;
    private final IExceptPhoneService exceptPhoneService;
    private final IRuleTemplateService ruleTemplateService;
    @Lazy
    private final IProductService productService;
    @Lazy
    private final IOrderRecordService orderRecordService;
    private final IScoreRecordService scoreRecordService;
    private final IYxSmsService yxSmsService;
    private final IInviteService inviteService;
    private final ICompanyService companyService;
    private final IInviteTemplateService inviteTemplateService;
    /**
     * RSA私钥
     */
    @Value("${RSA.privateKey}")
    private String privateKey;

    /**
     * RSA公钥
     */
    @Value("${RSA.publicKey}")
    private String publicKey;

    @Autowired
    public CustomerServiceImpl(
            @Lazy IOrderRecordService orderRecordService,
            @Lazy IProductService productService,
            Environment env,
            RedisClient redisClient,
            IPhoneIspService phoneIspService,
            ISmsRuleService ruleService,
            IBlackListService blackListService,
            IFeedbackRecordService feedbackRecordService,
            IExceptPhoneService exceptPhoneService,
            IRuleTemplateService ruleTemplateService,
            IScoreRecordService scoreRecordService,
            IYxSmsService yxSmsService,
            IInviteService inviteService,
            ICompanyService companyService,
            IInviteTemplateService inviteTemplateService

    ) {
        this.orderRecordService = orderRecordService;
        this.productService = productService;
        this.env = env;
        this.redisClient = redisClient;
        this.phoneIspService = phoneIspService;
        this.ruleService = ruleService;
        this.blackListService = blackListService;
        this.feedbackRecordService = feedbackRecordService;
        this.exceptPhoneService = exceptPhoneService;
        this.ruleTemplateService = ruleTemplateService;
        this.scoreRecordService = scoreRecordService;
        this.yxSmsService = yxSmsService;
        this.inviteService = inviteService;
        this.companyService = companyService;
        this.inviteTemplateService = inviteTemplateService;
    }

    /**
     * 查询C端用户列表
     */
    @Override
    public ResultData getPaging(QueryCustomerModel model) {
        String phone = model.getPhone();
        Integer validFlag = model.getValidFlag();
        Integer memberLevel = model.getMemberLevel();
        Integer memberStatus = model.getMemberStatus();
        String bt = model.getBeginCreateTime();
        String et = model.getEndCreateTime();
        Page page = new Page(model.getPageNum(), model.getPageSize());
        IPage<Customer> dtoIPage = this.getBaseMapper().selectPage(page,
                new LambdaQueryWrapper<Customer>().like(StringUtils.isNotBlank(phone), Customer::getPhone, phone)
                        .eq(validFlag != null, Customer::getValidFlag, validFlag)
                        .eq(memberLevel != null, Customer::getMemberLevel, memberLevel)
                        .eq(memberStatus != null, Customer::getMemberStatus, memberStatus)
                        .ge(StringUtils.isNotBlank(bt), Customer::getCreateTime, bt)
                        .le(StringUtils.isNotBlank(et), Customer::getCreateTime, et)
                        .orderByDesc(Customer::getCustomerId)
        );
        return ResultData.successData(dtoIPage);
    }
    /**
     * 批量设置黑名单
     */
    @Transactional(rollbackFor = SysException.class)
    @Override
    public ResultData setBlackList(List<String> phoneList) {
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        String customerPhone = customer.getPhone();
        for (String blackPhone : phoneList) {
            BlackList blackList = blackListService.getOne(new LambdaQueryWrapper<BlackList>().eq(BlackList::getCustomerId, customerId).eq(BlackList::getBlackPhone, blackPhone));
            if (blackList == null) {
                blackList = new BlackList(blackPhone, customerId, customerPhone);
                blackListService.save(blackList);
            }
        }
        return ResultData.success();
    }

    /**
     * 批量取消黑名单
     */
    @Override
    public ResultData cancelBlackList(List<String> phoneList) {
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        for (String blackPhone : phoneList) {
            BlackList blackList = blackListService.getOne(new LambdaQueryWrapper<BlackList>().eq(BlackList::getCustomerId, customerId).eq(BlackList::getBlackPhone, blackPhone));
            if (blackList != null) {
                blackListService.removeById(blackList);
            }
        }
        return ResultData.success();
//        return ResultData.failure(ErrorEnums.SQL_ERROR, "");
    }

    /**
     * APP 获取短信验证码，5分钟有效 注册和登录都需要使用
     */
    @Override
    public ResultData getSmsVerifyCode(String phone) {
        try {
            if (!phone.matches(PHONE_NUMBER_VALID_REGEX)) {
                return ResultData.failure("手机号码格式错误");
            }
            String key = phone + "_smsVerifyCode";
            String smsVerifyCode = redisClient.getJsonString(key);
            if (StringUtils.isNotBlank(smsVerifyCode)) {
                return ResultData.successData(smsVerifyCode);
            }
            log.info("运行环境:{}", env.getActiveProfiles());

            //注意峰哥的手机号是官方的测试号，无法发送登录的验证码，默认验证码为123456
            if (Arrays.asList(env.getActiveProfiles()).contains("dev")||SystemConstants.APP_TEST_PHONE.equals(phone)) {
                // 生产环境使用固定验证码
                smsVerifyCode = "123456";
            } else {
                // 非生产环境使用随机验证码
                smsVerifyCode = VerifyCodeUtil.generateTextCode(TYPE_NUM_ONLY, 6, null);
            }
//            smsVerifyCode = VerifyCodeUtil.generateTextCode(TYPE_NUM_ONLY, 6, null);
            redisClient.save(key, smsVerifyCode, 5 * 60);
            if (SystemConstants.APP_TEST_PHONE.equals(phone)||Arrays.asList(env.getActiveProfiles()).contains("dev")){
                ResultData result = ResultData.successMsg("短信发送成功");
                result.setData(smsVerifyCode);
                return result;
            }
            String sign= SignEnum.getSign(1);
            SendSmsModel sendSmsModel = new SendSmsModel(
                    phone, String.format("【%s】您正在通过手机号登录，验证码为 %s，有效期 5 分钟。此验证码仅用于本次登录，请勿向他人泄露。", sign, smsVerifyCode)
            );
            ResultData result = SmsPyUtil.sendCommonSms(sendSmsModel);
            log.info("短信发送结果:={}", JSON.toJSONString(result));
            return ResultData.successMsg("短信发送成功");
        } catch (Exception e) {
            log.error("获取短信验证码异常: {}", e.getMessage());
            return ResultData.failure("获取短信验证码异常");
        }
    }

    /*
     * @Transactional(rollbackFor = SysException.class)是事务回滚配置*/

    /**
     * APP 注册或登录
     */
    @Override
    @Transactional(rollbackFor = SysException.class)
    public ResultData appRegisterOrLogin(RegisterOrLoginModel model) {
        String phone = model.getPhone();
        if (!phone.matches(PHONE_NUMBER_VALID_REGEX)) {
            return ResultData.failure("手机号码格式错误");
        }
        //校验验证码
        String key = phone + "_smsVerifyCode";
        String redisVerifyCode = redisClient.getJsonString(key);

        if (StringUtils.isBlank(redisVerifyCode)) {
            return ResultData.failure("验证码不存在，请重新获取");
        }
        String smsVerifyCode = model.getSmsVerifyCode();
        if (!redisVerifyCode.equals(smsVerifyCode)) {
            return ResultData.failure("验证码错误，请重新输入");
        }
        Customer customer = getOne(new LambdaQueryWrapper<Customer>()
                .eq(Customer::getPhone, phone)
                .eq(Customer::getValidFlag, VALID_TRUE));
        LocalDateTime now = LocalDateTime.now();

        //未注册 ，执行注册
        if (customer == null) {
            customer = new Customer();
//            BeanUtils.copyProperties(model, customer);
            //注册用户为非会员
            customer.setPhone(phone);

            //customer 表 省市存中文
            String prePhone = phone.substring(0, 7);
            String password = SaSecureUtil.rsaEncryptByPublic(publicKey, phone.substring(5, 11));
//            String password = phone.substring(phone.length() - 6, phone.length());
            log.info("注册用户密码:={}", password.length());
            customer.setPassword(password);
            PhoneIsp phoneIsp = phoneIspService.getOne(new LambdaQueryWrapper<PhoneIsp>()
                    .eq(PhoneIsp::getPhone, prePhone));
            if (phoneIsp != null) {
                customer.setProvince(phoneIsp.getProvince());
                customer.setCity(phoneIsp.getCity());
            }
            customer.setCreator(phone);
            customer.setUpdater(phone);
            customer.setRegisterTime(now);
            customer.setCreateTime(now);
            /*新注册送12个月会员 start*/
            /*获取产品*/
            Product product = productService.getOne(new LambdaQueryWrapper<Product>().eq(Product::getProductId,3));
            customer.setMessageNumTotal(product.getMonthSmsQuantity());
            customer.setMessageNum(product.getMonthSmsQuantity());
            customer.setCurrentQuantity(product.getMonthSmsQuantity());
            customer.setSmsTotal(product.getMonthSmsQuantity());
            customer.setMemberClearTime(now.plusMonths(product.getPeriod()));
            customer.setMemberExpireTime(now.plusMonths(12));
            customer.setRoleId(RoleEnum.MEMBER.roleType);
            customer.setMemberStatus(MEMBER_STATUS_TRUE);
            /*新注册送12个月会员  end*/
//            /*不赠送 start*/
//            customer.setMessageNumTotal(NUMBER_0);
//            customer.setMessageNum(NUMBER_0);
//            customer.setCurrentQuantity(NUMBER_0);
//            customer.setSmsTotal(NUMBER_0);
//            customer.setRoleId(RoleEnum.COMMON.roleType);
//            customer.setMemberStatus(MEMBER_STATUS_FALSE);
//            /*不赠送 end*/

            customer.setSmsThaliNumTotal(NUMBER_0);
            customer.setSmsThaliNum(NUMBER_0);
            customer.setMemberScore(NUMBER_0);
            customer.setMemberLevel(MEMBER_LEVEL_0);
            customer.setChannelType(CHANNEL_TYPE_PLATFORM);
            customer.setUpdateTime(now);
            customer.setLastLoginTime(now);
//            customer.setSign(PLATFORM_SIGN_CONTENT);
            customer.setIsPlatformSign(IS_PLATFORM_SIGN_TRUE);
            customer.setCurrentSendTimes(NUMBER_0);
            customer.setPhoneSendTimes(NUMBER_0);
            customer.setPlatformSendTimes(NUMBER_0);
            customer.setSendTimes(NUMBER_0);
            customer.setConsumeAmount(BigDecimal.valueOf(NUMBER_0));
            customer.setOrderTimes(NUMBER_0);
            customer.setLoginTimes(NUMBER_0 + 1);
            customer.setValidFlag(VALID_TRUE);
            customer.setSignVerifyStatus(NUMBER_0);
            boolean customerFlag = save(customer);
            Company company = new Company();
            company.setPhone(phone);
            company.setCustomerId(customer.getCustomerId());
            company.setCreatorId(customer.getCustomerId());
            company.setUpdaterId(customer.getCustomerId());
            company.setCreateTime(now);
            company.setUpdateTime(now);
            company.insert();

            for(int i = 0; i < 12; i++){
                OrderRecord orderRecord = new OrderRecord();
                orderRecord.setOrderNum(String.valueOf(System.currentTimeMillis())+ new Random().nextInt(9999)+customer.getCustomerId());
                orderRecord.setThirdOrderNumber("666666666666");
                orderRecord.setCustomerId(customer.getCustomerId());
                orderRecord.setPhone(phone);
                orderRecord.setProductId(product.getProductId());
                orderRecord.setProductType(product.getProductType());
                orderRecord.setPeriod(product.getPeriod());
                orderRecord.setFee(BigDecimal.valueOf(NUMBER_0));
                orderRecord.setMonthSmsQuantity(product.getMonthSmsQuantity());
                orderRecord.setPayType(NUMBER_0);
                orderRecord.setOrderStatus(PAY_STATUS_FREE);
                orderRecord.setSmsType(i==0?SMS_PACKAGE_STATUS_TRUE:SMS_PACKAGE_STATUS_DEFAULT);
                orderRecord.setExpireType(NUMBER_0);
                orderRecord.setCreateTime(now);
                orderRecord.setUpdateTime(now);
                orderRecord.setPayTime( now);
                orderRecord.setApplyTime(i==0?now:now.plusMonths(i).plusDays(1));
                orderRecord.setExpireTime(now.plusMonths(i+1));
                orderRecord.insert();
            }
            if (!customerFlag) {
                return ResultData.failure("注册失败，数据库错误");
            }
        } else {
            customer.setLastLoginTime(now);
            customer.setLoginTimes(customer.getLoginTimes() + 1);
            boolean customerFlag = updateById(customer);
            if (!customerFlag) {
                return ResultData.failure("登录失败，数据库错误");
            }
        }
        /*用户登录给用户新增一条邀请函*/
        log.info("customer用户登录：{}", customer.getCustomerId());
        Invite invite = inviteService.getOne(new LambdaQueryWrapper<Invite>().eq(Invite::getCustomerId, customer.getCustomerId()));
        if (invite == null) {
            YxSms yxSms=yxSmsService.getOne(new LambdaQueryWrapper<YxSms>().eq(YxSms::getYxSmsType,NUMBER_0)
                    .orderByAsc(YxSms::getCreateTime)
                    .last("LIMIT 1"));
            log.info("yxSms模板:{}",yxSms);
            invite = new Invite();
            invite.setCustomerId(customer.getCustomerId());
            invite.setYxSmsId(yxSms.getYxSmsId());
            InviteTemplate inviteTemplate = inviteTemplateService.getOne(new LambdaQueryWrapper<InviteTemplate>()
                    .eq(InviteTemplate::getValidFlag, VALID_TRUE)
                    .orderByAsc(InviteTemplate::getCreateTime)
                    .last("LIMIT 1")
            );
            invite.setInviteTemplateId(inviteTemplate.getInviteTemplateId());
            Company company = companyService.getOne(new LambdaQueryWrapper<Company>().eq(Company::getCustomerId, customer.getCustomerId())
                    .last("LIMIT 1")
            );
            log.info("登录company:{}",company);
            if (company != null){
                invite.setCompanyId(company.getCompanyId());
            }
            invite.insert();
        }else{
            if (invite.getCompanyId()==null){
                Company company = companyService.getOne(new LambdaQueryWrapper<Company>().eq(Company::getCustomerId, customer.getCustomerId())
                        .last("LIMIT 1")
                );
                log.info("登录company:{}",company);
                if (company != null){
                    invite.setCompanyId(company.getCompanyId());
                }
            }
            invite.updateById();
        }
        log.info("customer用户登录：{}", customer);
        //写入缓存
        StpUtil.login(customer.getCustomerId(), SystemConstants.APP);
        StpUtil.getTokenSession().set(SystemConstants.APP + "_" + customer.getCustomerId().toString(), customer);
//        法1
        AppGetLoginModel loginModel = new AppGetLoginModel(customer);
        ResultData resultData = ResultData.success();
        resultData.setToken(StpUtil.getTokenValue());
        resultData.setSuccess(true);
        // 设置DTO对象
        resultData.setData(loginModel);
        //向登录记录表中存入数据loginRecordService
        LoginRecord loginRecord = new LoginRecord();
        loginRecord.setEntityName(TABLE_NAME_CUSTOMER);
        loginRecord.setEntityId(customer.getCustomerId());
        loginRecord.setLoginTime(now);
        loginRecord.insert();
        redisClient.delete(key);
        return resultData;
//        法2
//        return ResultData.successData(customer);
    }


    /**
     * 更新个人信息
     */
    @Override
    public ResultData updateOwnInfo(UpdateCustomerModel model) {
        log.info("更新个人信息：{}", model);
        // 查询当前登录用户id
        Long customerId = StpUtil.getLoginIdAsLong();
        String birthdayStr = model.getBirthday();
        LocalDate birthday = DateTimeUtil.String2LocalDate(birthdayStr);
        // 先更新数据库
        boolean updateResult = update(new LambdaUpdateWrapper<Customer>()
                .set(Customer::getNickname, model.getNickname())
                .set(Customer::getBirthday, birthday)
                .set(Customer::getSex, model.getSex())
                .set(Customer::getAvatar, model.getAvatar())
                .set(Customer::getBirthdayType, model.getBirthdayType())
                .eq(Customer::getCustomerId, customerId));

        if (updateResult) {
            // 重新获取最新用户数据
            Customer updatedCustomer = getById(customerId);
            // 更新 TokenSession 中的用户对象（关键修改）
            StpUtil.getTokenSession().set(
                    SystemConstants.APP + "_" + customerId.toString(),
                    updatedCustomer
            );
        }
        //获取当前登录信息
        Customer customer = getById(customerId);
        AppGetLoginModel loginModel = new AppGetLoginModel(customer);
        ResultData resultData = ResultData.success();
        resultData.setData(loginModel);
        String cacheKey = APP + "_" + customer.getCustomerId();
        // 使用标准JSON序列化
        redisClient.save(cacheKey, JSON.toJSONString(customer));
        return resultData;
    }


    @Override
    public ResultData setSign(SetSignModel model) {
        //判断operatorIdCard身份证格式是否正确
        if (!model.getOperatorIdCard().matches(IDENTITY_REG)) {
            return ResultData.failure("经办人身份证号码格式不正确");
        }
        if (!StringUtils.isBlank(model.getLegalPersonIdCard())) {
            if (!model.getLegalPersonIdCard().matches(IDENTITY_REG)) {
                return ResultData.failure("法人身份证号码格式不正确");
            }
        }
        Long customerId = null;
        Integer status=null;
        if(model.getCustomerId()==null){
            customerId = StpUtil.getLoginIdAsLong();
            status=SIGN_VERIFY_STATUS_DEFAULT;
        }else{
            customerId =model.getCustomerId();
            status=SIGN_VERIFY_STATUS_PASS;
        }
        // 先更新数据库
        boolean updateResult = update(new LambdaUpdateWrapper<Customer>()
                .set(Customer::getSignVerify, model.getSignVerify())
                .set(Customer::getCompName, model.getCompName())
                .set(Customer::getCreditCode, model.getCreditCode())
                .set(Customer::getSignPic, model.getSignPic())
                .set(Customer::getLegalPersonName, model.getLegalPersonName())
                .set(Customer::getLegalPersonIdCard, model.getLegalPersonIdCard())
                .set(Customer::getOperatorName, model.getOperatorName())
                .set(Customer::getOperatorIdCard, model.getOperatorIdCard())
                .set(Customer::getOperatorPic, model.getOperatorPic())
                .set(Customer::getAptitudePic, model.getAptitudePic())
                .set(Customer::getSignVerifyStatus, status)
                .set(Customer::getSignVerifyRemark, "")
                .set(model.getCustomerId()!=null,Customer::getSign, model.getSignVerify())
                .set(model.getCustomerId()!=null,Customer::getSignVerifyTime, LocalDateTime.now())
                .eq(Customer::getCustomerId, customerId));

        if (updateResult) {
            // 重新获取最新用户数据
            Customer updatedCustomer = getById(customerId);
            // 更新 TokenSession 中的用户对象（关键修改）
            StpUtil.getTokenSession().set(
                    SystemConstants.APP + "_" + customerId.toString(),
                    updatedCustomer
            );
        }
        return updateResult ? ResultData.success() : ResultData.failure("更新失败");
    }


    @Override
    public ResultData setPlatformSign(Integer isPlatformSign) {
        Long customerId = StpUtil.getLoginIdAsLong();
        Customer customer = getById(customerId);
        log.info("customer:{}",customer);
        if (StringUtils.isEmpty(customer.getSign())&&isPlatformSign==0){
            return ResultData.failure("没有审核通过的签名");
        }
        // 先更新数据库
        boolean updateResult = update(new LambdaUpdateWrapper<Customer>()
                //isPlatformSign转成数字
                .set(Customer::getIsPlatformSign, isPlatformSign)
                .eq(Customer::getCustomerId, customerId));

        if (updateResult) {
            // 重新获取最新用户数据
            Customer updatedCustomer = getById(customerId);
            // 更新 TokenSession 中的用户对象（关键修改）
            StpUtil.getTokenSession().set(
                    SystemConstants.APP + "_" + customerId,
                    updatedCustomer
            );
        }
        return updateResult ? ResultData.success() : ResultData.failure("更新失败");
    }

    /*** 按查询条件导出查询C端用户列表 */
    @Override
    public void export(QueryCustomerModel model, HttpServletResponse response) {
        String phone = model.getPhone();
        Integer validFlag = model.getValidFlag();
        Integer memberLevel = model.getMemberLevel();
        Integer memberStatus = model.getMemberStatus();
        String bt = model.getBeginCreateTime();
        String et = model.getEndCreateTime();
        try {
            Page page = new Page(DEFAULT_EXPORT_START, MYBATIS_EXPORT);
            String[] headers = new String[]{"用户ID", "用户号码", "会员等级", "用户状态", "可用积分"};
            String[] fields = new String[]{"customerId", "phone", "memberLevel", "memberStatus", "memberScore"};
            //TODO 如果会员等级要搞成中文，那么可以在 Customer 里面加一个字段，对查询结果循环处理
            LambdaQueryWrapper wrapper = new LambdaQueryWrapper<Customer>()
//                    .select(Customer::getCustomerId, Customer::getPhone, Customer::getMemberLevel, Customer::getMemberStatus, Customer::getMemberScore)
                    .eq(StringUtils.isNotBlank(phone), Customer::getPhone, phone)
                    .eq(validFlag != null, Customer::getValidFlag, validFlag)
                    .eq(memberLevel != null, Customer::getMemberLevel, memberLevel)
                    .eq(memberStatus != null, Customer::getMemberStatus, memberStatus)
                    .ge(StringUtils.isNotBlank(bt), Customer::getCreateTime, bt)
                    .le(StringUtils.isNotBlank(et), Customer::getCreateTime, et)
                    .orderByDesc(Customer::getCustomerId);
            int count = this.getBaseMapper().selectCount(wrapper);
            if (count > DEFAULT_EXPORT_MAX) {
                List<String> list = new ArrayList<>(1);
                list.add("导出数量" + count + "不能大于" + DEFAULT_EXPORT_MAX);
                ExportExcelUtil.exportExcel("短信发送记录.xls", headers, fields, list, response);
                return;
            }
            IPage<Customer> dtoIPage = this.getBaseMapper().selectPage(page, wrapper);

            ExportExcelUtil.exportExcel("短信发送记录.xls", headers, fields, dtoIPage.getRecords(), response);
        } catch (Exception e) {
            log.error("导出异常,异常信息:{}", e.getMessage());
        }
    }

    /**
     * 通过ID用户查询C端用户详情
     */
    @Override
    public ResultData getInfoById(Long customerId) {
        //查询 1 用户资料 2 统计信息 3 用户标签
        //1 查询用户资料
        Customer customer = getById(customerId);
        if (customer == null) {
            return ResultData.failure("用户ID在库里不存在");
        }
        //2 也在 customer 里面： 统计信息 包括 消费总金额 订单记录数量 可用积分 登录次数 本机发送短信量 网关短信发送量

        //3 用户标签 是 tradeInfo 字段以逗号分隔

        return ResultData.successData(customer);
    }

    /**
     * 通过ID更新C端用户标签
     */
    @Override
    public ResultData updateTradeById(UpdateTradeModel model) {
        Long customerId = model.getCustomerId();
        Customer customer = getById(customerId);
        if (customer == null) {
            return ResultData.failure("用户ID在库里不存在");
        }
        String tradeInfo = model.getTradeInfo();
        boolean result = this.update(new LambdaUpdateWrapper<Customer>().eq(Customer::getCustomerId, customerId)
                .set(Customer::getTradeInfo, tradeInfo));
        if (result) {
            return ResultData.success();
        } else {
            return ResultData.failure("数据库出错");
        }
    }

    /**
     * 功能设置-发送通道 及 例外号码
     */
    @Transactional(rollbackFor = SysException.class)
    @Override
    public ResultData setChannelAndExceptList(Integer channelType, List<String> phoneList) {
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();

        int channelTypeDb = customer.getChannelType();
        if (channelTypeDb != channelType) {
            update(new LambdaUpdateWrapper<Customer>().set(Customer::getChannelType, channelType).eq(Customer::getCustomerId, customerId));
        }

        for (String exPhone : phoneList) {
            int count = exceptPhoneService.count(new LambdaQueryWrapper<ExceptPhone>().eq(ExceptPhone::getCustomerId, customerId).eq(ExceptPhone::getExPhone, exPhone));
            if (count <= 0) {
                ExceptPhone exceptPhone = new ExceptPhone(exPhone, customerId, customer.getPhone());
                exceptPhoneService.save(exceptPhone);
            }
        }
        return ResultData.success();
    }

    /**
     * 设置密码
     */
    @Override
    public ResultData setPassword(SetPasswordModel model) {
        // 查询最新用户数据
        Customer customer = SaTokenUtilPy.getCustomer();
        if (!customer.getPassword().equals(model.getPassword())) {
            return ResultData.failure("原密码错误");
        }
        if (!model.getNewPassword().equals(model.getConfirmPassword())) {
            return ResultData.failure("两次密码输入必须一致");
        }
        if (customer.getPassword().equals(model.getNewPassword())) {
            return ResultData.failure("原密码与新密码重复");
        }
        update(new LambdaUpdateWrapper<Customer>().set(Customer::getPassword, model.getNewPassword()).eq(Customer::getCustomerId, customer.getCustomerId()));
        return ResultData.success();
    }

    /**
     * APP 密码登录
     */
    @Override
    public ResultData appPwdLogin(AppLoginModel model) {
        String phone = model.getPhone();
        Customer customer;
        customer = getByPhone(phone);
        if (customer == null) {
            return ResultData.failure("手机号码不存在");
        }
        //已注册 执行登录
        if (customer != null) {
            if (VALID_TRUE != customer.getValidFlag()) {
                return ResultData.failure("用户已注销，请重新注册");
            }
        }
        String password = model.getPassword();
        if (!customer.getPassword().equals(password)) {
            return ResultData.failure("密码错误");
        }
        LocalDateTime now = LocalDateTime.now();
        customer.setLastLoginTime(now);
        customer.setLoginTimes(customer.getLoginTimes() + 1);
        boolean customerFlag = updateById(customer);
        if (!customerFlag) {
            return ResultData.failure("登录失败，数据库错误");
        }
        //写入缓存
        StpUtil.login(customer.getCustomerId(), SystemConstants.APP);
        StpUtil.getTokenSession().set(SystemConstants.APP + "_" + customer.getCustomerId().toString(), customer);
        AppGetLoginModel loginModel = new AppGetLoginModel(customer);
        ResultData resultData = ResultData.success();
        resultData.setToken(StpUtil.getTokenValue());
        resultData.setSuccess(true);
        // 设置DTO对象
        resultData.setData(loginModel);
        LoginRecord loginRecord = new LoginRecord();
        loginRecord.setEntityName(TABLE_NAME_CUSTOMER);
        loginRecord.setEntityId(customer.getCustomerId());
        loginRecord.setLoginTime(now);
        loginRecord.insert();
        return resultData;
    }

    @Override
    public ResultData<List<Customer>> analyseExcelCustomer(File file) {
//        String userName = currentUser.getName();
        LocalDateTime now = LocalDateTime.now();
        ZipSecureFile.setMinInflateRatio(-1.0d);
        ExcelReader reader = ExcelUtil.getReader(file);
        reader.setIgnoreEmptyRow(false);
        List<List<Object>> readAll = reader.read();
        List<Customer> records = new ArrayList<>();
        Customer record;
        List<Object> temp;
        if (readAll == null || readAll.size() == 1) {
            //只有标题没有内容
            return ResultData.failure("导入文件没有数据");
        }
        StringBuilder error = new StringBuilder();
        for (int i = 1; i < readAll.size(); i++) {
            temp = readAll.get(i);
            log.info(StringUtils.join(temp, ","));

            String phone = FileUtils.listGetTrim(temp, 0);
            //校验格式
            if (!phone.matches(PHONE_NUMBER_REGEX) && !phone.matches(LANDLINE_REGEX)) {
                error.append("企业号码 " + phone + " 不符合座机和手机号码的格式！");
                continue;
            }
            //如果号码已经在库里，就不再导入
            record = getByPhone(phone);
//            if (record == null) {
//                record = new Customer(phone, FROM_TYPE_PERSON, currentUser.getName(), "", "","");
//            } else {
//                continue;
//            }

//            record.setCreator(userName);
            record.setCreateTime(now);
            records.add(record);
        }
        if (error.length() != 0) {
            //说明有错误
            return ResultData.failure("导入数据存在错误：" + error.toString().substring(5));
        }
        return ResultData.successData(records);
    }

    @Override
    public Customer getByPhone(String phone) {
        if (StringUtils.isBlank(phone)) {
            throw new SysException("phone不能为空");
        }
        Customer customer = getOne(new LambdaQueryWrapper<Customer>().eq(Customer::getPhone, phone)
                .eq(Customer::getValidFlag, VALID_TRUE));
        return customer;
    }

    @Override
    public boolean checkByPhone(String phone) {
        if (StringUtils.isBlank(phone)) {
            throw new SysException("phone不能为空");
        }
        int count = count(new LambdaQueryWrapper<Customer>().eq(Customer::getPhone, phone));
        return count > 0 ? true : false;
    }

    /**
     * 导入用户
     */
    @Override
    public ResultData saveUploadCustomer(List<Customer> list) {
//        StringBuilder sb = new StringBuilder();
        boolean result = this.saveOrUpdateBatch(list);
        if (result) {
            return ResultData.success();
        }
        return ResultData.failure(ErrorEnums.SQL_ERROR, "");
    }


    public static void main(String[] args) {
        String phone = "13012345678";
        System.out.println(phone.substring(0, 7));
    }

    /**
     * 获取app当前登录用户信息
     */
    @Override
    public ResultData getUserInfo() {
        Long customerId = SaTokenUtilPy.getCustomer().getCustomerId();
        Customer customer = getById(customerId);

        if (customer == null) {
            return ResultData.failure("用户不存在");
        }

        StpUtil.getTokenSession().set(
                SystemConstants.APP + "_" + customerId.toString(),
                customer
        );
        GetUserInfoModel model = new GetUserInfoModel(customer);
        log.info("用户信息已返回:[{}]", model);
        return ResultData.successData(model);
    }

    /**
     * 获取app当前用户签名
     */
    @Override
    public ResultData getUserSign() {
        // 查询最新用户数据
        Long customerId = SaTokenUtilPy.getCustomer().getCustomerId();
        Customer customer = getById(customerId);
        if (customer == null) {
            return ResultData.failure("用户不存在");
        }
        log.info("数据签名：{}", customer);
        log.info("用户数据：{}", customer.getSignVerify());
        StpUtil.getTokenSession().set(
                SystemConstants.APP + "_" + customerId.toString(),
                customer
        );
        GetSignModel model = new GetSignModel(customer);
        log.info("数据签名：{}", model);
        return ResultData.successData(model);
    }

    /**
     * 注销账号
     */
    @Override
    public ResultData cancelAccount() {
        //修改当前账号存在状态valid_flag改为0
        Customer customer = SaTokenUtilPy.getCustomer();
        if (customer == null) {
            return ResultData.failure("用户不存在");
        }
        customer.setValidFlag(VALID_FALSE);
        customer.setCancelTime(LocalDateTime.now());
        boolean flag = updateById(customer);
        //删除相关的黑名单
//        blackListService.remove(new LambdaQueryWrapper<BlackList>().eq(BlackList::getCustomerId, customer.getCustomerId()));
//        feedbackRecordService.remove(new LambdaQueryWrapper<FeedbackRecord>().eq(FeedbackRecord::getCustomerId, customer.getCustomerId()));
//        exceptPhoneService.remove(new LambdaQueryWrapper<ExceptPhone>().eq(ExceptPhone::getCustomerId, customer.getCustomerId()));
//        ruleService.remove(new LambdaQueryWrapper<SmsRule>().eq(SmsRule::getCustomerId, customer.getCustomerId()));
//        ruleTemplateService.remove(new LambdaQueryWrapper<RuleTemplate>().eq(RuleTemplate::getCustomerId, customer.getCustomerId()));
        //用户注销保留数据，仅仅关闭功能
        List<SmsRule> list=ruleService.list(new LambdaQueryWrapper<SmsRule>().eq(SmsRule::getCustomerId, customer.getCustomerId()));
        list.forEach(item->{
            item.setValidFlag(VALID_FALSE);
            item.updateById();
        });
        if (flag) {
            return ResultData.success();
        } else {
            return ResultData.failure("注销失败");
        }
    }

    /**
     * 签名列表
     */
    @Override
    public ResultData getSignList(QuerySignModel model) {
        String phone = model.getPhone();
        Integer signVerifyStatus = model.getSignVerifyStatus();
        String bt = model.getBeginSt();
        String et = model.getEndSt();
        Page page = new Page(model.getPageNum(), model.getPageSize());
        IPage<Customer> dtoIPage = this.getBaseMapper().selectPage(page,
                new LambdaQueryWrapper<Customer>()
                        .like(StringUtils.isNotBlank(phone), Customer::getPhone, phone)
                        .eq(signVerifyStatus != null, Customer::getSignVerifyStatus, signVerifyStatus)
                        .ge(StringUtils.isNotBlank(bt), Customer::getSignVerifyTime, bt)
                        .le(StringUtils.isNotBlank(et), Customer::getSignVerifyTime, et)
                        .isNotNull(Customer::getSignVerify)
                        .ne(Customer::getSignVerify, "")
//                        .isNotNull(Customer::getSignPic)
//                        .ne(Customer::getSignPic, "")
                        .eq(Customer::getValidFlag, VALID_TRUE)
                        .orderByAsc(Customer::getSignVerifyStatus)
                        .orderByDesc(Customer::getCustomerId));

        // 修复分页转换逻辑
        IPage<GetSignModel> resultPage = dtoIPage.convert(GetSignModel::new);
        return ResultData.successData(resultPage);

//        return ResultData.successData(dtoIPage);
    }

    /**
     * 签名状态变更
     */
    @Override
    public ResultData updateStatus(UpdateStatusModel model) {
        SysUser sysUser = SaTokenUtilPy.getSysUser();
        Customer customer = getOne(new LambdaQueryWrapper<Customer>().eq(Customer::getCustomerId, model.getCustomerId()));
        if (customer == null) {
            return ResultData.failure("用户不在库里");
        }

        //修改上传的用户状态
        customer.setSignVerifyStatus(model.getSignVerifyStatus());
        customer.setSignVerifyRemark(model.getSignVerifyRemark());
        customer.setSignVerifyTime(LocalDateTime.now());
        customer.setVerifyUserId(sysUser.getUserId());
        if (model.getSignVerifyStatus() == SIGN_VERIFY_STATUS_PASS) {
            customer.setSign(customer.getSignVerify());
            BeanUtils.copyProperties(model, customer);
//            customer.setSignVerify("");
        }
        boolean flag = updateById(customer);
        if (flag) {
            return ResultData.success();
        } else {
            return ResultData.failure("修改失败");
        }
    }


    /**
     * 会员修改用户信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changeCustomer(Long customerId, Long productId, Long orderRecordId) {
        // 1. 数据校验
        Customer customer = getById(customerId);
        log.info("用户：{}", customer);
        Product product = productService.getById(productId);
        if (customer == null || product == null) {
            log.error("用户或套餐不存在 customerId:{}, productId:{}", customerId, productId);
            return false;
        }

        // 2. 积分处理
        processScore(customer, product,orderRecordId);

        // 3. 套餐类型处理
        switch (product.getProductType()) {
            case PRODUCT_TYPE_MEMBER:
                handleMemberProduct(customer, product);
                log.info("会员");
                break;
            case PRODUCT_TYPE_SMS:
                handleSmsProduct(customer, product);
                log.info("短信333");
                break;
            default:
                handleOtherProduct(customer, product);
                log.info("加量包");
        }
        // 4. 公共字段更新
        customer.setOrderTimes(customer.getOrderTimes() + 1);
        OrderRecord orderRecord = orderRecordService.getById(orderRecordId);
        customer.setConsumeAmount(customer.getConsumeAmount().add(orderRecord.getFee()));
        log.info("更新用户信息4444：{}", customer);
        // 5. 更新操作
        boolean updateSuccess = updateById(customer);
        if (updateSuccess) {
            updateCustomerCache(customerId);
        }
        return updateSuccess;
    }

    // 新增方法：处理积分变更
    private void processScore(Customer customer, Product product,Long orderRecordId) {
        if (shouldProcessScore(customer, product)) {
            ScoreRecord scoreRecord = buildScoreRecord(customer, product,orderRecordId);
            scoreRecordService.save(scoreRecord);
            Integer score = customer.getMemberScore() + (int) Math.ceil(product.getFee().doubleValue() * 2);
            log.info("积分变更：{}", score);
            customer.setMemberScore(score);
            customer.setMemberLevel(getOrderRecordEnum(score));
        }
    }

    // 新增方法：处理会员套餐
    private void handleMemberProduct(Customer customer, Product product) {
        customer.setRoleId((long) ROLE_MEMBER);
        customer.setMemberStatus(MEMBER_STATUS_TRUE);

        LocalDateTime now = LocalDateTime.now();
        if (isExpired(customer.getMemberExpireTime())) {
            customer.setMemberExpireTime(now.plusMonths(product.getPeriod()));
            customer.setMemberClearTime(now.plusMonths(product.getPeriod()));
            resetMessageQuota(customer, product);
        }else{
            customer.setMemberExpireTime(customer.getMemberExpireTime().plusMonths(product.getPeriod()));
        }
        log.info("处理会员套餐2222:{}",customer);
    }

    // 新增方法：处理短信套餐（修复原代码错误）
    private void handleSmsProduct(Customer customer, Product product) {
        LocalDateTime now = LocalDateTime.now();
        if (isExpired(customer.getSmsExpireTime())) {
            customer.setSmsExpireTime(now.plusMonths(product.getPeriod()));
            customer.setSmsClearTime(now.plusMonths(product.getPeriod()));
            customer.setSmsTotal(customer.getSmsTotal() + product.getMonthSmsQuantity());
            customer.setCurrentQuantity(customer.getCurrentQuantity() + product.getMonthSmsQuantity());
            customer.setSmsThaliNum(customer.getSmsThaliNum() + product.getMonthSmsQuantity());
            customer.setSmsThaliNumTotal(customer.getSmsThaliNumTotal() + product.getMonthSmsQuantity());
        }else{
            customer.setSmsExpireTime(customer.getSmsExpireTime().plusMonths(product.getPeriod()));
        }
        log.info("处理短信套餐2222：{}", customer);
    }

    // 新增方法：处理其他类型套餐
    private void handleOtherProduct(Customer customer, Product product) {
        // 增加空值检查和默认值设置
        LocalDateTime smsClearTime = customer.getSmsClearTime() != null
                ? customer.getSmsClearTime()
                : LocalDateTime.now();
        LocalDateTime memberClearTime = customer.getMemberClearTime() != null
                ? customer.getMemberClearTime()
                : LocalDateTime.now();

        if (smsClearTime.isBefore(memberClearTime)) {
            resetMessageQuota(customer, product);
        } else {
            customer.setSmsThaliNum(customer.getSmsThaliNum() + product.getMonthSmsQuantity());
            customer.setSmsThaliNumTotal(customer.getSmsThaliNumTotal() + product.getMonthSmsQuantity());
            customer.setCurrentQuantity(customer.getCurrentQuantity() + product.getMonthSmsQuantity());
            customer.setSmsTotal(customer.getSmsTotal() + product.getMonthSmsQuantity());
        }
        log.info("处理其他类型套餐3333：{}", customer);
    }

    // 新增方法：重置消息配额
    private void resetMessageQuota(Customer customer, Product product) {
        customer.setMessageNum(customer.getMessageNum()+product.getMonthSmsQuantity());
        customer.setMessageNumTotal(customer.getMessageNumTotal()+product.getMonthSmsQuantity());
        customer.setCurrentQuantity(customer.getCurrentQuantity() + product.getMonthSmsQuantity());
        customer.setSmsTotal(customer.getSmsTotal() + product.getMonthSmsQuantity());
        log.info("重置消息配额4444：{}", customer);
    }

    // 新增方法：积分处理条件判断
    private boolean shouldProcessScore(Customer customer, Product product) {
        return customer.getMemberStatus() == MEMBER_STATUS_TRUE
                || product.getProductType() == PRODUCT_TYPE_MEMBER;
    }

    // 新增方法：构建积分记录
    private ScoreRecord buildScoreRecord(Customer customer, Product product,Long orderRecordId) {
        ScoreRecord record = new ScoreRecord();
        record.setCustomerId(customer.getCustomerId());
        record.setOrderRecordId(orderRecordId);
        record.setPhone(customer.getPhone());
        record.setChangeType(INTEGRAL_TYPE_ORDER);
        record.setBeforeScore(Long.valueOf(customer.getMemberScore()));
        record.setAfterScore(Long.valueOf(customer.getMemberScore() + (int) Math.ceil(product.getFee().doubleValue() * 2)));
        record.setChangeScore(Long.valueOf((int) Math.ceil(product.getFee().doubleValue() * 2)));
        record.setRecordTime(LocalDateTime.now());
        record.setValidFlag(VALID_TRUE);
        return record;
    }

    // 新增工具方法：过期判断
    private boolean isExpired(LocalDateTime expireTime) {
        return expireTime == null || expireTime.isBefore(LocalDateTime.now());
    }

    // 新增方法：更新缓存
    private void updateCustomerCache(Long customerId) {
        Customer updatedCustomer = getById(customerId);
        String cacheKey = APP + "_" + customerId;
        redisClient.save(cacheKey, JSON.toJSONString(updatedCustomer));
        log.info("用户缓存已更新 customerId:{}", customerId);
    }

    /**
     * 统计信息
     */
    @Override
    public ResultData getData(TimeModel model) {
        //获取总注册数
        Long totalRegistrations = (long) count(new LambdaQueryWrapper<Customer>().between(StringUtils.isNotBlank(model.getBeginSt()), Customer::getCreateTime, model.getBeginSt()+ " 00:00:00", model.getEndSt()+ " 23:59:59"));
        //会员总数
        Long totalMembers = (long) count(new LambdaQueryWrapper<Customer>().eq(Customer::getMemberStatus, MEMBER_STATUS_TRUE).between(StringUtils.isNotBlank(model.getBeginSt()), Customer::getCreateTime, model.getBeginSt()+ " 00:00:00", model.getEndSt()+ " 23:59:59"));
        //会员充值总额
        BigDecimal totalRecharges = getBaseMapper().selectSumConsumeAmount(model.getBeginSt()+ " 00:00:00", model.getEndSt()+ " 23:59:59");
        //今日充值人数
        LocalDateTime todayStart = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime todayEnd = LocalDateTime.now().with(LocalTime.MAX);
        Long todayRechargesCount = (long) orderRecordService.count(new LambdaQueryWrapper<OrderRecord>()
                .eq(OrderRecord::getOrderStatus, PAY_STATUS_SUCCESS)
                .between(OrderRecord::getPayTime, todayStart, todayEnd)
                .groupBy(OrderRecord::getCustomerId));
        //今日充值总额
        BigDecimal todayRechargesAmount = orderRecordService.sumTodayRecharge(todayStart, todayEnd);
        StatsDataModel statsData = StatsDataModel.builder()
                .totalRegistrations(totalRegistrations)
                .totalMembers(totalMembers)
                .totalRecharges(Optional.ofNullable(totalRecharges).orElse(BigDecimal.ZERO))
                .todayRechargesCount(todayRechargesCount)
                .todayRechargesAmount(Optional.ofNullable(todayRechargesAmount).orElse(BigDecimal.ZERO))
                .build();
        return ResultData.successData(statsData);
    }

    /**
     * 统计信息会员年龄
     */
    @Override
    public ResultData getDataAge(TimeModel model) {
        Long totalMembers = (long) count(new LambdaQueryWrapper<Customer>()
                .eq(Customer::getMemberStatus, MEMBER_STATUS_TRUE)
                .between(!StringUtils.isEmpty(model.getBeginSt()), Customer::getCreateTime, model.getBeginSt()+ " 00:00:00", model.getEndSt()+ " 23:59:59")
        );
        // 获取有效会员列表
        List<Customer> members = list(new LambdaQueryWrapper<Customer>()
                .eq(Customer::getMemberStatus, MEMBER_STATUS_TRUE)
                .between(!StringUtils.isEmpty(model.getBeginSt()), Customer::getCreateTime, model.getBeginSt()+ " 00:00:00", model.getEndSt()+ " 23:59:59")
                .isNotNull(Customer::getBirthday));
        AtomicLong age0 = new AtomicLong(0L);
        AtomicLong age20 = new AtomicLong(0L);
        AtomicLong age30 = new AtomicLong(0L);
        AtomicLong age40 = new AtomicLong(0L);
        AtomicLong age50 = new AtomicLong(0L);
        AtomicLong age60 = new AtomicLong(0L);

        members.forEach(member -> {
            int age = TimeUtils.getAge(member.getBirthday().toString());
            if (age < 20) {
                age0.incrementAndGet();
            } else if (age < 30) {
                age20.incrementAndGet();
            } else if (age < 40) {
                age30.incrementAndGet();
            } else if (age < 50) {
                age40.incrementAndGet();
            } else if (age < 60) {
                age50.incrementAndGet();
            } else {
                age60.incrementAndGet();
            }
        });
        //统计年龄返回给前端
        List<AgeDataModel> ageData = Arrays.asList(
                new AgeDataModel("20岁以下", age0.get()),
                new AgeDataModel("20-30岁", age20.get()),
                new AgeDataModel("30-40岁", age30.get()),
                new AgeDataModel("40-50岁", age40.get()),
                new AgeDataModel("50-60岁", age50.get()),
                new AgeDataModel("60岁以上", age60.get())
        );
        return ResultData.successData(ageData);
    }

    /**
     * 统计信息地区会员
     */
    @Override
    public ResultData getDataMap(TimeModel model) {
        QueryWrapper<Customer> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("province", "count(*) as count")
                .eq("member_status", MEMBER_STATUS_TRUE)
                // 修改日期范围查询方式
                .between(!StringUtils.isEmpty(model.getBeginSt()) && !StringUtils.isEmpty(model.getEndSt()),
                        "create_time",
                        model.getBeginSt()+ " 00:00:00", model.getEndSt()+ " 23:59:59")
                .groupBy("province")
                .orderByDesc("count");
        log.info("查询会员地区统计SQL:{}", queryWrapper);
        List<MapDataModel> provinceStats = listMaps(queryWrapper)
                .stream()
                .map(map -> new MapDataModel(
                        StringUtils.defaultIfBlank((String) map.get("province"), "未知地区"),
                        (Long) map.get("count")))
//                .limit(10)
                .collect(Collectors.toList());

        return ResultData.successData(provinceStats);
    }

    /**
     * 统计信息地区会员列表
     */
    @Override
    public ResultData getDataMapList(TimeModel model) {
        log.info("查询会员地区统计参数:{}", model);
        log.info("查询会员地区统计SQL:{}", !StringUtils.isEmpty(model.getBeginSt()) && !StringUtils.isEmpty(model.getEndSt()));
        QueryWrapper<Customer> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("province", "count(*) as count")
                .eq("member_status", MEMBER_STATUS_TRUE)
                // 修改日期范围查询方式
                .between(!StringUtils.isEmpty(model.getBeginSt()) && !StringUtils.isEmpty(model.getEndSt()),
                        "create_time",
                        model.getBeginSt()+ " 00:00:00", model.getEndSt()+ " 23:59:59")
                .groupBy("province")
                .orderByDesc("count");
        log.info("查询会员地区统计SQL:{}", queryWrapper);
        List<MapDataModel> provinceStats = listMaps(queryWrapper)
                .stream()
                .map(map -> new MapDataModel(
                        StringUtils.defaultIfBlank((String) map.get("province"), "未知地区"),
                        (Long) map.get("count")))
                .limit(10)
                .collect(Collectors.toList());

        return ResultData.successData(provinceStats);
    }
}
